package com.jfcloud.mall.order.service.impl;

import com.jfcloud.common.aspect.TokenUser;
import com.jfcloud.common.exception.BussinessException;
import com.jfcloud.common.http.RespData;
import com.jfcloud.common.utils.MapUtil;
import com.jfcloud.mall.order.domain.JfcloudOrder;
import com.jfcloud.mall.order.domain.JfcloudOrderDetail;
import com.jfcloud.mall.order.domain.dto.OrderSubmitForm;
import com.jfcloud.mall.order.domain.dto.OrderSubmitForm.OrderDetail;
import com.jfcloud.mall.order.domain.dto.OrderVo;
import com.jfcloud.mall.order.domain.dto.StorageDeductForm;
import com.jfcloud.mall.order.domain.dto.UserAccountDeductForm;
import com.jfcloud.mall.order.persistent.JfcloudOrderDetailService;
import com.jfcloud.mall.order.persistent.JfcloudOrderService;
import com.jfcloud.mall.order.rpc.feign.ProductServiceClient;
import com.jfcloud.mall.order.rpc.feign.StorageServiceClient;
import com.jfcloud.mall.order.rpc.feign.UserServiceClient;
import com.jfcloud.mall.order.service.OrderService;
import io.seata.spring.annotation.GlobalTransactional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class OrderServiceImpl implements OrderService{
	private static final Logger LOGGER = LoggerFactory.getLogger(OrderServiceImpl.class);


	@Autowired
	private JfcloudOrderService jfcloudOrderService;
	@Autowired
	private JfcloudOrderDetailService jfcloudOrderDetailService;
	@Autowired
	private ProductServiceClient productServiceClient;
	@Autowired
	private StorageServiceClient storageServiceClient;
	@Autowired
	private UserServiceClient userServiceClient;

	@GlobalTransactional
	@Override
	public OrderVo createOrder(OrderSubmitForm orderInfo, TokenUser tokenUser,String token) {
		OrderVo vo= new OrderVo();
		List<JfcloudOrderDetail> details = new ArrayList<JfcloudOrderDetail>();
		JfcloudOrder order = createJfcloudOrder(orderInfo, tokenUser);
		//持久化订单
		jfcloudOrderService.save(order);
		//【RPC】调用商品查询服务 加载商品数据，进行生单
		RespData productDetails = productServiceClient.getProductDetails(orderInfo.aclPrdList());
		if(productDetails.getStatus()==RespData.Success) {
			BigDecimal amout=new BigDecimal(0d);
			List<Map<String,Object>> productList = (List<Map<String,Object>>)productDetails.getDatas();
			for(OrderDetail po :orderInfo.getDetails()) {
				Map<String,Object> productDetail = productList.stream().filter(
						(Map m)->MapUtil.getLong("id",m).equals(po.getProductId()))
						.collect(Collectors.toList()).get(0);
				//计算订单金额
				amout = amout.add( new BigDecimal(MapUtil.getDouble("price", productDetail))
						.multiply(new BigDecimal(po.getProductNum()) ) );
				JfcloudOrderDetail detail = createJfcloudOrderDetail(order, amout, po, productDetail);
				jfcloudOrderDetailService.save(detail);
				details.add(detail);
				//【RPC】调用库存扣减服务 (暂未实现批量扣减)
				deductStorage(new StorageDeductForm(po.getProductId(),Long.valueOf(po.getProductNum()),order.getId()));
			}
			order.setOrderAmout(amout);
			order.setOrderNo("OD"+order.getId());
			jfcloudOrderService.saveOrUpdate(order);
			// 【RPC】调用余额扣减服务
			deductUserAccount(new UserAccountDeductForm(token,amout,order.getId(),orderInfo.aclPrdNum()));
		}else {
			throw new BussinessException("商品数据获取失败:"+productDetails.getMeta());
		}
		vo.setOrder(order);
		vo.setDetails(details);
		return vo;
	}

	private JfcloudOrder createJfcloudOrder(OrderSubmitForm orderInfo, TokenUser tokenUser) {
		JfcloudOrder order= new JfcloudOrder();
		order.setUserId(tokenUser.getUserId());
		order.setUserName(tokenUser.getUserName());
		order.setProductNum(orderInfo.aclPrdNum());
		order.setCreateTime(LocalDateTime.now());
		order.setStatus(0);
		order.setPayStatus(0);
		order.setIsDelete(0);
		return order;
	}

	private JfcloudOrderDetail createJfcloudOrderDetail(JfcloudOrder order, BigDecimal amout, OrderDetail po, Map<String, Object> productDetail) {
		JfcloudOrderDetail detail = new JfcloudOrderDetail();
		//构建订单明细
		detail.setOrderId(order.getId());
		detail.setAmout(amout);
		detail.setNum(po.getProductNum());
		detail.setProductId(po.getProductId());
		detail.setProductName(MapUtil.getString("name",productDetail));
		detail.setPrice(new BigDecimal(MapUtil.getDouble("price", productDetail)));
		return detail;
	}

	private void deductUserAccount(UserAccountDeductForm userAccountDeductForm) {
		RespData rd =userServiceClient.deduct(userAccountDeductForm);
		if(RespData.Success==rd.getStatus()){
			LOGGER.info("扣减余额成功:"+userAccountDeductForm);
		}else{
			throw new BussinessException("扣减余额失败:"+rd.getMeta());
		}
	}

	private void deductStorage(StorageDeductForm storageDeductForm) {
		RespData rd = storageServiceClient.deductStorage(storageDeductForm);
		if(RespData.Success==rd.getStatus()){

			LOGGER.info("扣减库存成功:"+storageDeductForm);
		}else{
			throw new BussinessException("扣减库存失败:"+rd.getMeta());
		}
	}


}
